use tokio_modbus::prelude::*;
use tokio_modbus::client::Context;
use std::time::Duration;
use tracing::info;

use crate::config::{DeviceConfig, ProtocolType, PointConfig};
use crate::error::{Result, ModbusCollectorError};

/// Modbus 客户端管理器
#[derive(Debug, Clone)]
pub struct ModbusClientManager {
    // 移除客户端缓存，每次创建新的连接以避免线程安全问题
}

impl ModbusClientManager {
    pub fn new() -> Self {
        Self {
        }
    }
    
    /// 创建或获取Modbus客户端
    pub async fn get_client(&self, device: &DeviceConfig) -> Result<Context> {
        match device.protocol {
            ProtocolType::ModbusTcp => self.create_tcp_client(device).await,
            ProtocolType::ModbusRtu => self.create_rtu_client(device).await,
        }
    }
    
    /// 创建TCP客户端
    async fn create_tcp_client(&self, device: &DeviceConfig) -> Result<Context> {
        // 解析连接字符串 "IP:Port"
        let parts: Vec<&str> = device.connection.split(':').collect();
        if parts.len() != 2 {
            return Err(ModbusCollectorError::Config(
                format!("Invalid TCP connection string: {}", device.connection)
            ));
        }
        
        let ip = parts[0];
        let port: u16 = parts[1].parse()
            .map_err(|_| ModbusCollectorError::Config(
                format!("Invalid port in connection string: {}", device.connection)
            ))?;
        
        info!("Connecting to Modbus TCP device {} at {}:{}", device.device_id, ip, port);
        
        // 创建TCP连接
        let socket_addr = format!("{}:{}", ip, port).parse()
            .map_err(|_| ModbusCollectorError::Config(
                format!("Invalid socket address: {}:{}", ip, port)
            ))?;
        
        let client = tcp::connect_slave(socket_addr, Slave(device.slave_id)).await?;
        
        info!("Successfully connected to Modbus TCP device {}", device.device_id);
        Ok(client)
    }
    
    /// 创建RTU客户端
    async fn create_rtu_client(&self, device: &DeviceConfig) -> Result<Context> {
        
        // 解析连接字符串 "COM1:9600,8,N,1"
        let parts: Vec<&str> = device.connection.split(':').collect();
        if parts.len() != 2 {
            return Err(ModbusCollectorError::Config(
                format!("Invalid RTU connection string: {}", device.connection)
            ));
        }
        
        let port_name = parts[0];
        let params: Vec<&str> = parts[1].split(',').collect();
        if params.len() != 4 {
            return Err(ModbusCollectorError::Config(
                format!("Invalid RTU parameters: {}", parts[1])
            ));
        }
        
        let baud_rate: u32 = params[0].parse()
            .map_err(|_| ModbusCollectorError::Config(
                format!("Invalid baud rate: {}", params[0])
            ))?;
        
        let data_bits = match params[1] {
            "8" => tokio_serial::DataBits::Eight,
            "7" => tokio_serial::DataBits::Seven,
            _ => return Err(ModbusCollectorError::Config(
                format!("Unsupported data bits: {}", params[1])
            )),
        };
        
        let parity = match params[2] {
            "N" => tokio_serial::Parity::None,
            "E" => tokio_serial::Parity::Even,
            "O" => tokio_serial::Parity::Odd,
            _ => return Err(ModbusCollectorError::Config(
                format!("Unsupported parity: {}", params[2])
            )),
        };
        
        let stop_bits = match params[3] {
            "1" => tokio_serial::StopBits::One,
            "2" => tokio_serial::StopBits::Two,
            _ => return Err(ModbusCollectorError::Config(
                format!("Unsupported stop bits: {}", params[3])
            )),
        };
        
        info!("Connecting to Modbus RTU device {} on {}", device.device_id, port_name);
        
        // 创建串口配置
        let mut port = tokio_serial::new(port_name, baud_rate)
            .data_bits(data_bits)
            .parity(parity)
            .stop_bits(stop_bits)
            .timeout(Duration::from_millis(device.timeout))
            .open()?;
        let client = tokio_modbus::client::rtu::attach_slave(port, Slave(device.slave_id)).await?;
        
        info!("Successfully connected to Modbus RTU device {}", device.device_id);
        Ok(client)
    }
    
    /// 读取线圈
    pub async fn read_coils(&self, device: &DeviceConfig, address: u16, count: u16) -> Result<Vec<bool>> {
        let mut client = self.get_client(device).await?;
        let result = client.read_coils(address, count).await?;
        Ok(result)
    }
    
    /// 读取离散输入
    pub async fn read_discrete_inputs(&self, device: &DeviceConfig, address: u16, count: u16) -> Result<Vec<bool>> {
        let mut client = self.get_client(device).await?;
        let result = client.read_discrete_inputs(address, count).await?;
        Ok(result)
    }
    
    /// 读取输入寄存器
    pub async fn read_input_registers(&self, device: &DeviceConfig, address: u16, count: u16) -> Result<Vec<u16>> {
        let mut client = self.get_client(device).await?;
        let result = client.read_input_registers(address, count).await?;
        Ok(result)
    }
    
    /// 读取保持寄存器
    pub async fn read_holding_registers(&self, device: &DeviceConfig, address: u16, count: u16) -> Result<Vec<u16>> {
        let mut client = self.get_client(device).await?;
        let result = client.read_holding_registers(address, count).await?;
        Ok(result)
    }
    
    /// 写入单个线圈
    pub async fn write_single_coil(&self, device: &DeviceConfig, address: u16, value: bool) -> Result<()> {
        let mut client = self.get_client(device).await?;
        client.write_single_coil(address, value).await?;
        Ok(())
    }
    
    /// 写入单个寄存器
    pub async fn write_single_register(&self, device: &DeviceConfig, address: u16, value: u16) -> Result<()> {
        let mut client = self.get_client(device).await?;
        client.write_single_register(address, value).await?;
        Ok(())
    }
    
    /// 写入多个线圈
    pub async fn write_multiple_coils(&self, device: &DeviceConfig, address: u16, values: &[bool]) -> Result<()> {
        let mut client = self.get_client(device).await?;
        client.write_multiple_coils(address, values).await?;
        Ok(())
    }
    
    /// 写入多个寄存器
    pub async fn write_multiple_registers(&self, device: &DeviceConfig, address: u16, values: &[u16]) -> Result<()> {
        let mut client = self.get_client(device).await?;
        client.write_multiple_registers(address, values).await?;
        Ok(())
    }
    
    /// 根据点位配置读取数据
    pub async fn read_point_data(&self, device: &DeviceConfig, point: &PointConfig) -> Result<Vec<u16>> {
        let address = self.get_modbus_address(point.address)?;
        let count = self.get_register_count(&point);
        
        let data = match point.address {
            1..=65536 => {
                // 线圈
                let coils = self.read_coils(device, address, count).await?;
                coils.into_iter().map(|b| if b { 1 } else { 0 }).collect()
            },
            100001..=165536 => {
                // 离散输入
                let inputs = self.read_discrete_inputs(device, address, count).await?;
                inputs.into_iter().map(|b| if b { 1 } else { 0 }).collect()
            },
            300001..=365536 => {
                // 输入寄存器
                self.read_input_registers(device, address, count).await?
            },
            400001..=465536 => {
                // 保持寄存器
                self.read_holding_registers(device, address, count).await?
            },
            _ => {
                return Err(ModbusCollectorError::Config(
                    format!("Invalid Modbus address: {}", point.address)
                ));
            }
        };
        
        Ok(data)
    }
    
    /// 获取Modbus地址（转换为0基址）
    fn get_modbus_address(&self, address: u32) -> Result<u16> {
        match address {
            1..=65536 => Ok((address - 1) as u16),
            100001..=165536 => Ok((address - 100001) as u16),
            300001..=365536 => Ok((address - 300001) as u16),
            400001..=465536 => Ok((address - 400001) as u16),
            _ => Err(ModbusCollectorError::Config(
                format!("Invalid Modbus address: {}", address)
            )),
        }
    }
    
    /// 获取寄存器数量（根据数据类型）
    fn get_register_count(&self, point: &PointConfig) -> u16 {
        use crate::config::DataType;
        match point.data_type {
            DataType::Bool | DataType::Int16 | DataType::UInt16 => 1,
            DataType::Int32 | DataType::UInt32 | DataType::Float32 => 2,
            DataType::Float64 => 4,
        }
    }
    
    /// 断开所有连接
    pub async fn disconnect_all(&self) {
        info!("Modbus client manager does not cache connections");
        // 不需要断开缓存的连接，因为我们现在不再缓存它们
    }
}